iT邦幫忙

2022 iThome 鐵人賽

DAY 26
0
Software Development

你知道Go是什麼嗎?系列 第 26

Day26 - gRPC - Golang

  • 分享至 

  • xImage
  •  

要學習的東西太多了,最後幾天有點亂掉,今天就來研究gRPC吧。

RPC

RPCRemote Procedure Calls(遠端程序呼叫)的簡稱。一種遠端遠端調用程式的模組,可以讓遠端程式可以透過網路通訊方法呼叫本地functionmethod的一種方法。簡單一點的解說,今天有A、B兩台伺服器,A伺服器想要呼叫B伺服器提供的函式,但因為不在同一個空間,不能直接呼叫,透過網路通訊方法模擬直接從本地呼叫的樣式,即為RPC

概念大概如下:

  1. Client從遠端呼叫一個function
  2. function的參數會被打包成特定格式的封包
  3. 網路傳送封包
  4. Server接收封包
  5. 將封包轉換成可執行本地function的參數格式
  6. 執行此function後朝client回傳result

目的

  • 提供分散式系統間溝通的方法
  • 隱藏實作方法,與呼叫自己的方法一樣

gRPC

gRPC(Remote Procedure Calls)是Google發起的一個開源的RPC系統。可以更輕鬆地創建分佈式應用程序和服務。

特色

  • Protobuf格式傳輸資料
  • HTTP/2通訊協定,效能好
  • 支援雙向串流
  • 支持多種開發語言

傳輸方式

  • 單向傳輸(Unary):一個request,一個response,與一般http請求一樣,只是是透過gRPC協定。
  • 單向串流(Streaming)client發送一個request後,server可以多次response
  • 雙向串流(Bidirectional streaming):同WebSocket,傳輸格式透過schema定義,兩邊都可以多次requestreponse

透過Go使用gRPC

由於版本更新之前網路上相關文章有些使用方法已經不能使用了,目前統整的是我自己能使用的方式。

載入相關套件

  • protobuf go get -u google.golang.org/protobuf
  • gRPC go get -u google.golang.org/grpc
  • protobuf-compiler
    這篇文的內容設置好windows的Protocol Compiler

在終端機輸入下面兩行,
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest

這樣基本套件應該都載入好了。

撰寫Protobuf檔

在開發之前要先撰寫Protobuf檔,定義資料交換的相關資料,因此建立一個以proto為副檔名的檔案。

syntax = "proto3"; 

option go_package = "./protobuffer";
//定義Service名稱,
service SaySomethingService{ 
  //定義api名稱,傳入參數與回傳值
    rpc TestRPC (testRequest) returns (testResponse) {}
}

//傳入參數的spec
message testRequest {
    int64  id = 1;  
}

//回傳值的spec
message testResponse {
    string  name = 1;
    float   heigh = 2;
    float   weight = 3;
}

在參數後的 = <數字> ;是指輸入與輸出順序。相關方法定義好後,在終端機輸入以下指令

protoc --go_out=. --go-grpc_out=. test.proto

執行後會依照上方option go_package放入兩個.pb.go的檔案,這就是protoc編譯器幫忙使用定義好的proto檔產生的go檔案。

實作server與client端

正常來說兩份檔案應該要指向同一支protobuffer,我這邊偷懶了一下兩邊都編譯出了.pb.go

server

package main

import (
	"context"
	"log"
	"net"
	pb "grpc-test/protobuffer"
	"google.golang.org/grpc"
)

const (
	port = ":8080"
)

type server struct{}

func main() {
	// Create gRPC Server
	lis, err := net.Listen("tcp", port)
	if err != nil {
		log.Fatalf("failed to listen: %v", err)
	}
	s := grpc.NewServer()
	log.Println("gRPC server is running.")
	pb.RegisterSaySomethingServiceServer(s, &server{})
	if err := s.Serve(lis); err != nil {
		log.Fatalf("failed to serve: %v", err)
	}
}

//
func (s *server) TestRPC(ctx context.Context, in *pb.TestRequest) (*pb.TestResponse, error) {
	log.Println("i receive:", in.Id)
	return &pb.TestResponse{Name: "Jay", Weight: 75, Heigh: 170}, nil
}

這邊執行下來&server{}那邊會出錯,貌似是因為interface沒有將所有功能實作完,我有到test_grpc.pb.go中將下面功能做註解。

type SaySomethingServiceServer interface {
	// 定義api名稱,傳入參數與回傳值
	TestRPC(context.Context, *TestRequest) (*TestResponse, error)
    // 註解掉下面這行
	// MustEmbedUnimplementedSaySomethingServiceServer()
}

順利的話應該能執行起來讓伺服器運行。

client

用另一支Go程式模擬客戶端,這邊只是隨意發送一筆int值,讓server端回傳寫好的內容而已,實際運用時這邊可以做function的調用。

package main

import (
	"context"
	pb "grpc-client/protobuffer"
	"log"
	"time"
	"google.golang.org/grpc"
)

const (
	address = "localhost:8080"
)

func main() {

	conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
	if err != nil {
		log.Fatalf("did not connect: %v", err)
	}
	defer conn.Close()
	c := pb.NewSaySomethingServiceClient(conn)
	TestRPC(c, 12)

}

//
func TestRPC(c pb.SaySomethingServiceClient, id int64) {

	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	res, err := c.TestRPC(ctx, &pb.TestRequest{Id: id })
	if err != nil {
		log.Fatalf("could not mkdfk2020: %v", err)
	}
	log.Printf("gRPC response: %s", res)
}

server output:
2022/10/11 13:09:16 gRPC server is running.
2022/10/11 13:09:25 i receive: 12

client output:
2022/10/11 13:09:25 gRPC response: name:"Jay" heigh:170 weight:75

缺點

  • 不能透過瀏覽器直接調用gRPC服務。
  • gRPC是使用Protobuf進行編碼,雖可高效率傳送,但人工不可讀。
  • 使用時須先定義Protobuf規範,雖嚴謹但較費時。

gRPC就介紹到這吧,原本以為都照著別人的腳步走應該可以學很快,結果遇到版本更新問題,滿多地方照做都出錯,額外花了許多時間來整理今天的筆記,希望可以幫到閱讀者以及未來的自己ˊˇˋ


參考資料

Day29-Go gRPC(下)
https://ithelp.ithome.com.tw/articles/10278704

[DAY20]GO gRPC初體驗
https://ithelp.ithome.com.tw/articles/10243863

Day31 Golang Protobuf 介紹與使用
https://ithelp.ithome.com.tw/articles/10250131

plugins are not supported : grpc #1070
https://github.com/golang/protobuf/issues/1070

DAY9 — 神奇的 gRPC,讓你把 call service 當成一個 function call — 概念篇
https://ithelp.ithome.com.tw/articles/10242372

使用 Golang 建立一個 gRPC 架構
https://keronscribe.tw/golang-grpc-unary

Day 16 - 分散式系統溝通的方法 - RPC
https://ithelp.ithome.com.tw/articles/10223580


上一篇
Day25 - WebSocket簡易聊天室 - Golang
下一篇
Day27 - GraphQL - Golang
系列文
你知道Go是什麼嗎?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言